﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Thread = System.Threading.Tasks;
using Microsoft.Practices.Unity;
using Infrastucture;
using Infrastucture.Collections;
using TimeSplicerModule.Factories;
using TimeSplicerModule.DomainModels;
using TimeSplicerModule.Security;
using TimeSplicerModule.ViewModels;

namespace TimeSplicerModule.Services
{
    public partial class ProjectService : IProjectService
    {
        public ProjectViewModel CreateNew()
        {
            _session = _container.Resolve<ISession>();
            var project = _projectFactory.CreateNew();

            // defaults
            project.StartedDate = DateTime.Now;
            project.DueDate = project.StartedDate.AddMonths(3).Date;
            project.EstimatedHours = 120;

            project.Categories = _categoryService.GetSelectableProjectCategories();
            project.Category = project.Categories.FirstOrDefault();
            project.CategoryGuid = project.Category.CategoryGuid;

            project.Priorities = _session.Priorities; //_priorityFactory.GetList();
            project.PriorityGuid = project.Priorities.FirstOrDefault(x => x.Priority == Infrastucture.Priority.Normal).PriorityGuid;


            

            project.ProjectManagers = _userService.GetSelectableProjectManagers();
            project.ProjectManager = project.ProjectManagers.FirstOrDefault(x => x.UserGuid == _session.User.UserGuid);
            project.ProjectManagerGuid = project.ProjectManager.UserGuid;

            project.Users = _userFactory.GetList(); // Get all users, anyone can be invited
            project.ProjectRoles = _projectRoleFactory.GetList();
            project.ProjectUsers = new List<ProjectUserModel>(); // default so that its not null 

            project.CreatedByGuid = _session.User.UserGuid;
            project.CreatedBy = _session.User;
            project.CreatedDate = DateTime.Now;

            var status = _session.Statuses.FirstOrDefault(x => x.StatusEnum == Infrastucture.Status.Not_Started.ToString()); //_statusFactory.Get(x => x.StatusEnum == Infrastucture.Status.Not_Started.ToString());
            project.Status = status;
            project.StatusGuid = status.StatusGuid;


            var users = _userFactory.GetList();

            project.ProjectRoles = _projectRoleFactory.GetList();
            project.ObservableProjectUsers = new ObservableCollection<ProjectUserModel>();

            var model = ModelConverter.ToModel<ProjectViewModel>(project);

            // set defaults - may have more to do:
            model.IsEnabled = true;
            model.UsersVilibility = System.Windows.Visibility.Visible;
            model.TasksVisibility = System.Windows.Visibility.Collapsed;
            model.CompletedDateVisibility = System.Windows.Visibility.Collapsed;
            model.ReportsVisibility = System.Windows.Visibility.Collapsed;

            // should probably allow project users to be selected

            return model;
        }

        public ProjectViewModel Save(ProjectViewModel project)
        {
            var p = ModelConverter.ToModel<ProjectModel>(project);
            p = Save(p);


            return GetViewModel(p.ProjectGuid);
        }

        public ProjectViewModel Complete(ProjectViewModel project)
        {
            // TODO: I think i just need to Change the status to complete then 
            var complete = _session.Statuses.FirstOrDefault(x => x.StatusEnum == Status.Completed.ToString());
            //_statusFactory.Get(x => x.StatusEnum == Status.Completed.ToString());

            project.StatusGuid = complete.StatusGuid;
            project.Status = complete;
            project.CompletedDate = DateTime.Now;

            project = Save(project);

            return GetViewModel(project.ProjectGuid);
        }

        public ProjectViewModel GetViewModel(Guid id)
        {
            _session = _container.Resolve<ISession>();
            var project = Get(id);


            var model = ModelConverter.ToModel<ProjectViewModel>(project);

            // TODO: may have more setup to do: also if only pm and above can edit, so may have to have gloabal disabled

            if (_session.User.ApplicationRole.Hierarchy > 0)
            {
                // set user permissions based on user project role

                if (model.ProjectManagers.FirstOrDefault(x => x.UserGuid == model.ProjectManagerGuid) == null)
                {
                    // get that user
                    var user = _userFactory.Get(x => x.UserGuid == model.ProjectManagerGuid);
                    model.ProjectManagers.Add(user);
                }

                if (model.Categories == null)
                    model.Categories = new List<CategoryModel>();

                if (model.Categories.FirstOrDefault(x => x.CategoryGuid == model.CategoryGuid) == null)
                {
                    var cat = _categoryFactory.Get(x => x.CategoryGuid == model.CategoryGuid);
                    model.Categories.Add(cat);
                }


                // some stuff is getting nulled out because of the user permissions at this point, need to probably fill that in here

                var projectRole = model.ProjectUsers.FirstOrDefault(x => x.UserGuid == _session.User.UserGuid);

                var projectPM = model.ProjectRoles.FirstOrDefault(x => x.Hierarchy == 1);

                if (projectRole.ProjectRole.Hierarchy == projectPM.Hierarchy)
                {
                    model.IsEnabled = true;
                    model.IsAddTaskButtonEnabled = true;
                    model.IsCompleteButtonEnabled = true;

                    if (model.ProjectGuid != Guid.Empty)
                        model.ReportsVisibility = System.Windows.Visibility.Visible;
                }
                else if (projectRole.ProjectRole.Hierarchy == projectPM.Hierarchy)
                {
                    model.IsEnabled = false;
                    model.IsAddTaskButtonEnabled = true;
                }
                else if (projectRole.ProjectRole.Hierarchy > projectPM.Hierarchy)
                {
                    model.IsAddTaskButtonEnabled = false;
                    model.IsEnabled = false;
                    model.ReportsVisibility = System.Windows.Visibility.Collapsed;
                }
                else
                {
                    model.IsEnabled = true;
                    model.IsAddTaskButtonEnabled = true;
                }
            }
            else
            {
                model.IsEnabled = true;
                model.IsAddTaskButtonEnabled = true;
                model.IsCompleteButtonEnabled = true;
            }

            model.UsersVilibility = System.Windows.Visibility.Visible;
            model.TasksVisibility = System.Windows.Visibility.Visible;

            if (model.Status.Status == Status.Completed)
            {
                model.IsAddTaskButtonEnabled = false;
                model.IsCompleteButtonEnabled = false;
                model.CompletedDateVisibility = System.Windows.Visibility.Visible;
            }
            else
            {
                model.CompletedDateVisibility = System.Windows.Visibility.Collapsed;
            }

            return model;
        }

        public ProjectViewModel AddUser(ProjectViewModel project, UserModel user, ProjectRoleModel projectRole)
        {
            // only add if project guid is enmpy
            if (project.ProjectGuid != Guid.Empty)
            {
                var projectUser = _projectUserFactory.CreateNew();
                projectUser.ProjectGuid = project.ProjectGuid;
                projectUser.UserGuid = user.UserGuid;
                projectUser.ProjectRoleGuid = projectRole.ProjectRoleGuid;

                projectUser = _projectUserFactory.Upsert(projectUser);

                projectUser.User = user;
                projectUser.ProjectRole = projectRole;

                project.ProjectUsers.Add(projectUser);
                project.ObservableProjectUsers = project.ProjectUsers.ToObservableCollection();
            }
            else // add only to model list if project is new
            {
                var projectUser = _projectUserFactory.CreateNew();

                projectUser.UserGuid = user.UserGuid;
                projectUser.ProjectRoleGuid = projectRole.ProjectRoleGuid;

                projectUser.User = user;
                projectUser.ProjectRole = projectRole;

                project.ProjectUsers.Add(projectUser);
                project.ObservableProjectUsers = project.ProjectUsers.ToObservableCollection();
            }

            return project;
        }
    }
}
